﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using Microsoft.Win32;
using SHDocVw;
using SpicIE.Common;

namespace SpicIE.Controls
{
    /// <summary>
    /// Creates either a new toolbar or explorer bar with user defined functionality and contents
    /// Code adaption of: http://support.microsoft.com/default.aspx?scid=kb;en-us;821793, http://msdn.microsoft.com/en-us/library/cc144099(VS.85).aspx
    /// </summary>
    [Browsable(false)]
    [DesignTimeVisible(false)]
    public class Toolbar : UserControl, IObjectWithSite, IControlBase, IDeskBand, IDockingWindow, IOleWindow, IInputObject, IOleCommandTarget
    {
        /// <summary>
        /// The PluginGuid _must_ be a unique GUID to identify and register the COM object correctly
        /// </summary>
        public virtual string PluginGuid { get { return String.Empty; } }
        /// <summary>
        /// The PluginProgID _must_ be provided to identify and register the COM object correctly
        /// </summary>
        public virtual string PluginProgID { get { return String.Empty; } }

        [ComVisible(false)]
        [CLSCompliant(false)]
        public IWebBrowser2 Explorer;
        [ComVisible(false)]
        private InternetExplorer BandObjectSite;

        [ComVisible(false)]
        private IInputObjectSite InputObjectSite;

        #region Member variables declaration

        [Browsable(true)]
        private Guid ToolbarID { get { return new Guid(PluginGuid); } }
        [Browsable(true)]
        private string ToolbarProgID { get { return PluginProgID; } }


        [Browsable(true)]
        protected string ToolbarTitle;
        [Browsable(true)]
        protected string ToolbarName;
        [Browsable(true)]
        protected Size MinSize;
        [Browsable(true)]
        protected Size MaxSize;
        [Browsable(true)]
        protected Size IntegralSize;
        [Browsable(true)]
        protected new Size Size;
        [Browsable(true)]
        protected Color BackgroundColor;
        [Browsable(true)]
        protected string ToolbarHelpText;
        [ComVisible(false)]
        protected ToolbarEnum ToolbarStyle = ToolbarEnum.Horizontal;

        [Browsable(true)]
        public string Title { get { return ToolbarTitle; } }
        [Browsable(true)]
        public string InternalName { get { return ToolbarName; } }
        [Browsable(true)]
        public Size ToolbarMinSize { get { return MinSize; } }
        [Browsable(true)]
        public Size ToolbarMaxSize { get { return MaxSize; } }
        [Browsable(true)]
        public Size ToolbarIntegralSize { get { return IntegralSize; } }
        [Browsable(true)]
        public Size ToolbarSize { get { return Size; } }
        [Browsable(true)]
        public Color ToolbarBackgroundColor { get { return BackgroundColor; } }
        [Browsable(true)]
        public string HelpText { get { return ToolbarHelpText; } }
        [ComVisible(false)]
        public ToolbarEnum Style { get { return ToolbarStyle; } }
        #endregion

        /// <summary>
        /// Specifies how the toolbar or explorer bar should be rendered
        /// </summary>
        [ComVisible(false)]
        public enum ToolbarEnum
        {
            Vertical = 1,
            ExplorerToolbar = 2,
            Horizontal = 4
        }

        #region Events
        public event ToolbarEvent_BeforeNavigate2 OnBeforeNavigate2;
        public event ToolbarEvent_Client2Host OnClient2Host;
        public event ToolbarEvent_OnQuit OnQuit;
        public event ToolbarEvent_OnVisible OnVisible;
        public event ToolbarEvent_OnExplorerAttached OnExplorerAttached;
        [CLSCompliant(false)]
        public event ToolbarEvent_OnWindowStateChanged OnWindowStateChanged;

        private void ToolbarEvent_BeforeNavigate2(object pDisp, ref object URL, ref object Flags, ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
        {
            try
            {
                if (OnBeforeNavigate2 != null)
                    lock (OnBeforeNavigate2) { OnBeforeNavigate2.Invoke(pDisp, ref URL, ref Flags, ref TargetFrameName, ref PostData, ref Headers, ref Cancel); }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "ToolbarEvent_BeforeNavigate2, error in invoke: " + ex);
            }
        }

        private void ToolbarEvent_Client2Host(ref int width, ref int height)
        {
            try
            {
                if (OnClient2Host != null)
                    lock (OnClient2Host) { OnClient2Host.Invoke(ref width, ref height); }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "ToolbarEvent_Client2Host, error in invoke: " + ex);
            }
        }

        private void ToolbarEvent_OnQuit()
        {
            try
            {
                if (OnQuit != null)
                    lock (OnQuit) { OnQuit.Invoke(); }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "ToolbarEvent_OnQuit, error in invoke: " + ex);
            }
        }

        private void ToolbarEvent_OnVisible(bool visible)
        {
            try
            {
                if (OnVisible != null)
                    lock (OnVisible) { OnVisible.Invoke(visible); }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "ToolbarEvent_OnVisible, error in invoke: " + ex);
            }
        }

        private void ToolbarEvent_OnExplorerAttached(EventArgs args)
        {
            try
            {
                if (OnExplorerAttached != null)
                    lock (OnVisible) { OnExplorerAttached.Invoke(args); }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "ToolbarEvent_OnExplorerAttached, error in invoke: " + ex);
            }
        }

        private void ToolbarEvent_OnWindowStateChanged(uint dwWindowStateFlags, uint dwValidFlagsMask)
        {
            try
            {
                if (OnWindowStateChanged != null)
                    lock (OnWindowStateChanged) { OnWindowStateChanged.Invoke(dwWindowStateFlags, dwValidFlagsMask); }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "ToolbarEvent_OnWindowStateChanged, error in invoke: " + ex);
            }
        }
        #endregion

        #region Toolbar constructor
        /// <summary>
        /// Global constructor
        /// </summary>
        public Toolbar()
        {
        }

        /// <summary>
        /// Constructor for the Toolbar class
        /// </summary>
        /// <param name="toolbarID">the id for the com object</param>
        /// <param name="toolbarName">the specified name for the object</param>
        /// <param name="toolbarTitle">the title to be shown</param>
        /// <param name="toolbarHelpText">the corrosponding help text</param>
        /// <param name="toolbarStyle">appearance of the toolbar</param>
        /// <param name="controls">containing list of controls</param>
        public Toolbar(Guid toolbarID, string toolbarName, string toolbarTitle, string toolbarHelpText, ToolbarEnum toolbarStyle, Control[] controls)
        {
            Host.TraceSink.TraceInformation("SpicIE: Toolbar " + toolbarName + " instantiated");
        }
        #endregion

        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);

            if (InputObjectSite != null)
            {
                InputObjectSite.OnFocusChangeIS(this, true);
            }
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);

            if (InputObjectSite != null)
            {
                InputObjectSite.OnFocusChangeIS(this, false);
            }
        }

        /// <summary>
        /// Function for creating the controls appearing on the toolbar or explorer bar
        /// </summary>
        /// <param name="controls">list of controls</param>
        public void BuildControls(Control[] controls)
        {
            if (controls != null && controls.Length != 0)
            {
                try
                {
                    this.SuspendLayout();
                    this.BackColor = ToolbarBackgroundColor;
                    //this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
                    this.Margin = new System.Windows.Forms.Padding(1);
                    this.Controls.AddRange(controls);
                    this.PerformLayout();
                    this.ResumeLayout(false);

                    //this.ShowBrowserBar(false);
                }
                catch (Exception ex)
                {
                    Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Controls.Toolbar in BuildControls - " + ex);
                }
            }
        }

        /// <summary>
        /// Makes the Toolbar visible or hides it
        /// </summary>
        /// <param name="visible"></param>
        public void ShowBrowserBar(bool visible)
        {
            SpicIE.Host.TraceSink.TraceInformation("Toolbar: ShowBrowserBar(" + visible + ") called (" + InternalName + " | " + ToolbarID + ")");

            try
            {
                if (Explorer == null)
                {
                    SpicIE.Host.TraceSink.TraceInformation("Explorer is null!");
                }
                else
                {
                    object pvaClsid = (object)(ToolbarID.ToString("B"));
                    object pvarShow = (object)visible;
                    object pvarSize = null;

                    // Hide Browser bar before showing to prevent erroneous behavior of IE
                    if (visible)
                    {
                        object pvarShowFalse = (object)false;
                        Explorer.ShowBrowserBar(ref pvaClsid, ref pvarShowFalse, ref pvarSize);
                    }

                    Explorer.ShowBrowserBar(ref pvaClsid, ref pvarShow, ref pvarSize);
                }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception (" + Thread.CurrentThread.ManagedThreadId + "): Controls.Toolbar (Show Browser Bar " + ToolbarName + ": " + visible.ToString() + "): " + ex);
            }
        }

        /// <summary>
        /// Show the current toolbar in case ob being the site as internet explorer and not IIObjectWithSite
        /// </summary>
        /// <param name="site"></param>
        private void ShowToolBar(object site)
        {
            SpicIE.Host.TraceSink.TraceInformation("Toolbar: ShowToolBar called (" + InternalName + " | " + ToolbarID + ")");

            try
            {
                InternetExplorer ie = site as InternetExplorer;
                if (ie == null)
                {
                    Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception (" + Thread.CurrentThread.ManagedThreadId + "): ShowToolbar " + site + " is null");
                    return;
                }

                object pvaClsid = (object)(ToolbarID.ToString("B"));
                object pvarSize = null;
                object pvarShowTrue = (object)true;

                ie.ShowBrowserBar(ref pvaClsid, ref pvarShowTrue, ref pvarSize);
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception (" + Thread.CurrentThread.ManagedThreadId + "): Controls.Toolbar error in ShowToolbar " + InternalName + " - " + ex);
            }
        }

        /// <summary>
        /// Gets the handle for the current window
        /// </summary>
        /// <param name="WindowPointer"></param>
        public void GetWindow(out IntPtr WindowPointer)
        {
            WindowPointer = Handle;
        }

        /// <summary>
        /// not implemented
        /// </summary>
        /// <param name="EnterMode"></param>
        public void ContextSensitiveHelp(bool EnterMode)
        {
        }

        /// <summary>
        /// Shows the explorer bar
        /// </summary>
        /// <param name="visible"></param>
        public void ShowDW(bool visible)
        {
            if (visible)
                Show();
            else
                Hide();
        }

        /// <summary>
        /// Destroys the explorer bar
        /// </summary>
        /// <param name="Reserved"></param>
        [CLSCompliant(false)]
        public void CloseDW(uint Reserved)
        {
            Dispose(true);
        }

        /// <summary>
        /// not implemented
        /// </summary>
        /// <param name="BorderPointer"></param>
        /// <param name="UnknownToolbarSite"></param>
        /// <param name="Reserved"></param>
        public void ResizeBorderDW(IntPtr BorderPointer, object UnknownToolbarSite, bool Reserved)
        {
        }

        /// <summary>
        /// Retrieves information about the current explorer bar or toolbar
        /// </summary>
        /// <param name="BandObjID"></param>
        /// <param name="ViewMode"></param>
        /// <param name="DeskBandInfo"></param>
        [ComVisible(false)]
        [CLSCompliant(false)]
        public void GetBandInfo(uint BandObjID, uint ViewMode, ref DESKBANDINFO DeskBandInfo)
        {
            try
            {
                SpicIE.Host.TraceSink.TraceInformation("Toolbar: GetBandInfo called(" + InternalName + " | " + ToolbarID + "), dwBandID: " + BandObjID);

                if ((DeskBandInfo.dwMask & DBIM.TITLE) == DBIM.TITLE)
                {
                    DeskBandInfo.wszTitle = Title;
                }

                if ((DeskBandInfo.dwMask & DBIM.ACTUAL) == DBIM.ACTUAL)
                {
                    DeskBandInfo.ptActual.X = Size.Width;
                    DeskBandInfo.ptActual.Y = Size.Height;
                }

                if ((DeskBandInfo.dwMask & DBIM.MAXSIZE) == DBIM.MAXSIZE)
                {
                    DeskBandInfo.ptMaxSize.X = ToolbarMaxSize.Width;
                    DeskBandInfo.ptMaxSize.Y = ToolbarMaxSize.Height;
                }

                if ((DeskBandInfo.dwMask & DBIM.MINSIZE) == DBIM.MINSIZE)
                {
                    DeskBandInfo.ptMinSize.X = ToolbarMinSize.Width;
                    DeskBandInfo.ptMinSize.Y = ToolbarMinSize.Height;
                }

                if ((DeskBandInfo.dwMask & DBIM.INTEGRAL) == DBIM.INTEGRAL)
                {
                    DeskBandInfo.ptIntegral.X = ToolbarIntegralSize.Width;
                    DeskBandInfo.ptIntegral.Y = ToolbarIntegralSize.Height;
                }

                if ((DeskBandInfo.dwMask & DBIM.MODEFLAGS) == DBIM.MODEFLAGS)
                {
                    DeskBandInfo.dwModeFlags = DBIMF.VARIABLEHEIGHT | DBIMF.NORMAL;
                }

                if ((DeskBandInfo.dwMask & DBIM.BKCOLOR) == DBIM.BKCOLOR)
                {
                    DeskBandInfo.dwMask &= ~DBIM.BKCOLOR;
                }
                if (Style == ToolbarEnum.ExplorerToolbar)
                    DeskBandInfo.dwModeFlags = DBIMF.BREAK | DBIMF.ALWAYSGRIPPER;

            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Controls.Toolbar error in GetBandInfo - " + ex);
            }
        }

        /// <summary>
        /// Tells the internet explorer that it's been activated
        /// </summary>
        /// <param name="active"></param>
        /// <param name="message"></param>
        [ComVisible(false)]
        [CLSCompliant(false)]
        public void UIActivateIO(int active, ref MSG message)
        {
            if (active != 0)
            {
                Control ctrl = GetNextControl(this, true);

                if (ModifierKeys == Keys.Shift)
                    ctrl = GetNextControl(ctrl, false);

                if (ctrl != null)
                    ctrl.Select();

                this.Focus();
            }
        }

        /// <summary>
        /// Informs about which window has focus
        /// </summary>
        /// <returns>Win32.S_OK or Win32.S_False</returns>
        public int HasFocusIO()
        {
            return this.ContainsFocus ? Win32.S_OK : Win32.S_FALSE; ;
        }

        /// <summary>
        /// Allows the object to process keyboard accelerators
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        [ComVisible(false)]
        [CLSCompliant(false)]
        public int TranslateAcceleratorIO(ref MSG message)
        {
            if (message.message == Win32.WM_KEYDOWN)
            {
                if (message.wParam == (uint)Keys.Tab || message.wParam == (uint)Keys.F6)
                {
                    if (SelectNextControl(ActiveControl, ModifierKeys == Keys.Shift ? false : true, true, true, false))
                    {
                        return Win32.S_OK;
                    }
                }
                else
                {
                    TranslateMessage(ref message);
                    DispatchMessage(ref message);
                    return Win32.S_OK;
                }
            }

            return Win32.S_FALSE;
        }

        [DllImport("user32.dll")]
        static extern int TranslateMessage(ref MSG lpMsg);

        [DllImport("user32", EntryPoint = "DispatchMessage")]
        static extern bool DispatchMessage(ref MSG msg);
        #region Transparency
        [DllImport("uxtheme", ExactSpelling = true)]
        public extern static Int32 DrawThemeParentBackground(IntPtr WindowPointer, IntPtr hdc, ref Rectangle RectanglePointer);

        /// <summary>
        /// Override for PaintBackground
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            if (this.BackColor == Color.Transparent)
            {
                IntPtr hdc = e.Graphics.GetHdc();
                Rectangle rec = new Rectangle(e.ClipRectangle.Left, e.ClipRectangle.Top, e.ClipRectangle.Width, e.ClipRectangle.Height);
                DrawThemeParentBackground(this.Handle, hdc, ref rec);
                e.Graphics.ReleaseHdc(hdc);
            }
            else
            {
                base.OnPaintBackground(e);
            }
        }
        #endregion

        #region COM object register functionality
        /// <summary>
        /// Global function for registering the com object
        /// </summary>
        public void Register()
        {
            try
            {
                string id = ToolbarID.ToString("B");
                if (String.IsNullOrEmpty(InternalName))
                    return;

                Host.RegisterCOMObject(this.GetType(), ToolbarID, ToolbarProgID);

                var mainKey = Registry.ClassesRoot.CreateSubKey(@"CLSID\" + id);

                var instance = mainKey.CreateSubKey("Instance");
                instance.SetValue("CLSID", "{4D5C8C2A-D075-11d0-B416-00C04FB90376}");
                var init = instance.CreateSubKey("InitPropertyBag");
                init.SetValue("Url", "");

                var subKey = mainKey.CreateSubKey("Implemented Categories");
                var sizeKey = Registry.CurrentUser.CreateSubKey(SpicIE.Constants.REGISTRY_TOOLBARSIZE + id);
                mainKey.SetValue("", InternalName);
                mainKey.SetValue("MenuText", InternalName);
                mainKey.SetValue("HelpText", HelpText);

                switch (Style)
                {
                    case ToolbarEnum.Horizontal:
                        subKey.CreateSubKey(SpicIE.Constants.REGISTRY_HORIZONTALKEY);
                        sizeKey.SetValue("BarSize", BitConverter.GetBytes(Size.Height));
                        break;
                    case ToolbarEnum.Vertical:
                        subKey.CreateSubKey(SpicIE.Constants.REGISTRY_VERTICALKEY);
                        sizeKey.SetValue("BarSize", BitConverter.GetBytes(Size.Width));
                        break;
                    case ToolbarEnum.ExplorerToolbar:
                        Registry.LocalMachine.CreateSubKey(SpicIE.Constants.REGISTRY_TOOLBARXTENSIONS).SetValue(id, InternalName);
                        break;
                }

                try
                {
                    var catKey = Registry.CurrentUser.OpenSubKey(SpicIE.Constants.REGISTRY_TOOLBARCATEGORIES, true);
                    if (catKey != null)
                    {
                        var delKeys = catKey.GetSubKeyNames();
                        foreach (string key in delKeys)
                        {

                            if (key == SpicIE.Constants.REGISTRY_COMPONENTENUM1)
                                catKey.OpenSubKey(SpicIE.Constants.REGISTRY_COMPONENTENUM1, true).DeleteSubKey("Enum", false);
                            if (key == SpicIE.Constants.REGISTRY_COMPONENTENUM2)
                                catKey.OpenSubKey(SpicIE.Constants.REGISTRY_COMPONENTENUM2, true).DeleteSubKey("Enum", false);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Controls.Toolbar error in deleting enums " + InternalName + ": " + ex);
                }
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Controls.Toolbar error in registering Toolbar " + InternalName + ": " + ex);
            }
        }

        /// <summary>
        /// global function for unregistering the com object
        /// </summary>
        public void Unregister()
        {
            try
            {
                var id = ToolbarID.ToString("B");

                Host.UnRegisterCOMObject(ToolbarID);

                if (Registry.ClassesRoot.OpenSubKey(SpicIE.Constants.REGISTRY_TOOLBARXTENSIONS + id) != null)
                    Registry.LocalMachine.CreateSubKey(SpicIE.Constants.REGISTRY_TOOLBARXTENSIONS).DeleteValue(id, false);


                //string[] keys = Registry.LocalMachine.OpenSubKey(SpicIE.Constants.REGISTRY_TOOLBARXTENSIONS, true).GetValueNames();
                //foreach (string value in keys)
                //    if(value == id)
                //        Registry.LocalMachine.CreateSubKey(SpicIE.Constants.REGISTRY_TOOLBARXTENSIONS).DeleteValue(id, false);
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0, "Exception: Controls.Toolbar error in unregistering Toolbar " + InternalName + ": " + ex);
            }
        }
        #endregion

        #region GetSite/SetSite functionality
        /// <summary>
        /// Global function for initialising the toolbar
        /// </summary>
        /// <param name="site"></param>
        public void SetSite(object site)
        {
            Host.TraceSink.TraceInformation("Toolbar: SetSite called (" + InternalName + " | " + ToolbarID +
                                                 ") HASH:" + GetHashCode());

            try
            {
                if (site is InternetExplorer)
                {
                    SpicIE.Host.TraceSink.TraceInformation("Toolbar: Site is InternetExplorer (" + InternalName +
                                                           " | " + ToolbarID + ")");

                    BandObjectSite = (InternetExplorer)site;

                    object queryObject = null;
                    Guid guid = Guid.Empty;
                    Guid riid = Guid.Empty;

                    try
                    {
                        Common.IServiceProvider sp = (Common.IServiceProvider)BandObjectSite;
                        guid = new Guid(SpicIE.Constants.IID_IWebBrowserApp);
                        riid = new Guid(SpicIE.Constants.IID_IUnknown);
                        sp.QueryService(ref guid, ref riid, out queryObject);
                    }
                    catch (Exception ex)
                    {
                        Host.TraceSink.TraceEvent(TraceEventType.Error, 0,
                                                  "Exception: Controls.Toolbar error in SetSite querying service provider (" +
                                                  InternalName + " | " + ToolbarID + ") Exception: " + ex);
                    }

                    try
                    {
                        Explorer = (IWebBrowser2)queryObject;
                        if (Explorer == null)
                            SpicIE.Host.TraceSink.TraceInformation("Toolbar: SetSite (" + InternalName + " | " +
                                                                   ToolbarID + ") Explorer is NULL!");
                        else
                        {
                            SpicIE.Host.TraceSink.TraceInformation("Toolbar: Explorer : " + GetHashCode());
                        }

                    }
                    catch (Exception ex)
                    {
                        Host.TraceSink.TraceEvent(TraceEventType.Error, 0,
                                                  "Exception: Controls.Toolbar error in SetSite retrieving explorer object (" +
                                                  InternalName + " | " + ToolbarID + ") Exception: " + ex);
                    }

                    ShowToolBar(BandObjectSite);
                }
                else if (site is IInputObjectSite)
                {
                    InputObjectSite = (IInputObjectSite)site;
                    SpicIE.Host.TraceSink.TraceInformation("Toolbar: Site is IInputObjectSite (" + InternalName +
                                                           " | " + ToolbarID + ")");
                }
                else if (site == null)
                {
                    SpicIE.Host.TraceSink.TraceInformation("Toolbar: Site equals null -> disposing (" + InternalName +
                                                           " | " + ToolbarID + ")");
                    if (BandObjectSite != null)
                    {
                        Marshal.ReleaseComObject(BandObjectSite);
                        BandObjectSite = null;
                    }
                    if (InputObjectSite != null)
                    {
                        Marshal.ReleaseComObject(InputObjectSite);
                        InputObjectSite = null;
                    }
                }


                OnSetSite();
            }
            catch (Exception ex)
            {
                Host.TraceSink.TraceEvent(TraceEventType.Error, 0,
                                          "Exception: Controls.Toolbar error in SetSite (" + InternalName + " | " +
                                          ToolbarID + ") Exception: " + ex);
            }
        }

        protected virtual void OnSetSite()
        {
            
        }

        /// <summary>
        /// Gets the current handle of the site
        /// </summary>
        /// <param name="riid"></param>
        /// <param name="site"></param>
        public void GetSite(ref Guid riid, out object site)
        {
            Host.TraceSink.TraceInformation("Toolbar: GetSite called (" + InternalName + " | " + ToolbarID + ") HASH:" + GetHashCode());
            site = BandObjectSite;
        }
        #endregion

        #region IOLECommandTarget interface implementation
        /// <summary>
        /// interface implementation for communicating with the ole object, in this case the menuitem as com object
        /// </summary>
        /// <param name="pguidCmdGroup"></param>
        /// <param name="cCmds"></param>
        /// <param name="prgCmds"></param>
        /// <param name="pCmdText"></param>
        /// <returns>-1</returns>
        [CLSCompliant(false)]
        public int QueryStatus(ref Guid pguidCmdGroup, uint cCmds, OLECMD[] prgCmds, IntPtr pCmdText)
        {
            Host.TraceSink.TraceEvent(TraceEventType.Information, 0, "Toolbar: QueryStatus = " + cCmds + " (" + InternalName + " | " + ToolbarID + ")");
            return -1;
        }

        /// <summary>
        /// interface implementation for firing the OLE Command event which can be subscribed in the intatiated class
        /// </summary>
        /// <param name="pguidCmdGroup"></param>
        /// <param name="nCmdID"></param>
        /// <param name="nCmdexecopt"></param>
        /// <param name="pvaIn"></param>
        /// <param name="pvaOut"></param>
        /// <returns>-1</returns>
        [CLSCompliant(false)]
        public int Exec(ref Guid pguidCmdGroup, uint nCmdID, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
        {
            Host.TraceSink.TraceEvent(TraceEventType.Information, 0, "Toolbar: Exec (nCmdID " + nCmdID + ") (" + InternalName + " | " + ToolbarID + ")");
            return -1;
        }

        /// <summary>
        /// Override for WinProc
        /// </summary>
        /// <param name="message"></param>
        protected override void WndProc(ref Message message)
        {
            if (message.Msg == Win32.WM_SETFOCUS)
            {
                this.InvokeGotFocus(this, EventArgs.Empty);
            }
            else if (message.Msg == Win32.WM_PARENTNOTIFY)
            {
                this.InvokeGotFocus(this, EventArgs.Empty);
            }
            else if (message.Msg == Win32.WM_WINDOWPOSCHANGED)
            {
                Graphics hdc = null;

                try
                {
                    hdc = Graphics.FromHwnd(this.Handle);
                    Rectangle rect = new Rectangle(this.Location, this.Size);
                    this.InvokePaintBackground(this, new PaintEventArgs(hdc, rect));
                }
                finally
                {
                    if (hdc != null)
                        hdc.Dispose();
                }
            }
            base.WndProc(ref message);
        }

        #endregion
    }
}
